﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Text;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
using System.Collections.ObjectModel;
using System.Linq;
namespace Skybot.Arcgis.Client.TileLayerExpand
{
    /// <summary>
    /// BingMap緩存地圖讀取,可以向將圖片部屬到本地機器上
    /// 用 這個圖層進行訪問
    /// </summary>
    public class TileLayerBingMapExpand : ESRI.ArcGIS.Client.TiledMapServiceLayer
    {

        #region 私有變數

        private string uriTemplate = "http://r2.tiles.ditu.live.com/tiles/r{quadkey}.png?g=49";

        private const int WKID = 0x18ee1;


        /// <summary>
        ///  全地圖最大顯示區域
        /// </summary>
        private Envelope _fullExtent = null;

        /// <summary>
        ///  本地圖最大放大倍數
        /// </summary>
        private int _MaxLevel = 17;
        /// <summary>
        ///  本地圖最小放大倍數
        /// </summary>
        private int _MinLevel = 1;
        #endregion

        #region 公共屬性
        /// <summary>
        /// 改變URL值
        /// </summary>
        public string UriTemplate
        {
            get { return uriTemplate; }
            set { uriTemplate = value; }
        }
        #endregion
        #region 構造函數



        /// <summary>
        /// 調用 默認的 在線地圖創建圖層
        /// </summary>
        public TileLayerBingMapExpand()
        {
            base.SpatialReference = new SpatialReference(WKID);
        }

        /// <summary>
        /// 創建一個新的對像
        /// </summary>
        /// <param name="RoadUriBuilder">示例 new UriBuilder("http://r2.tiles.ditu.live.com/tiles/r{quadkey}.png?g=49");</param>
        public TileLayerBingMapExpand(Uri RoadUriBuilder)
        {
            //線路URL
            uriTemplate = RoadUriBuilder.ToString();
            base.SpatialReference = new SpatialReference(WKID);
        }



        /// <summary>
        ///構造一個圖層
        /// </summary>
        /// <param name="RoadUriBuilder">示例 new UriBuilder("http://r2.tiles.ditu.live.com/tiles/r{quadkey}.png?g=49");</param>
        /// <param name="FullExtent">本地圖區域</param>
        public TileLayerBingMapExpand(Uri RoadUriBuilder, Envelope FullExtent)
        {
            //線路URL
            uriTemplate = RoadUriBuilder.ToString();
            /// <summary>
            ///  全地圖最大顯示區域
            /// </summary>
            this.FullExtent = FullExtent;
            /// <summary>
            ///  全地圖最大顯示區域
            /// </summary>
            _fullExtent = FullExtent;
            base.SpatialReference = new SpatialReference(WKID);
        }

        /// <summary>
        ///構造一個圖層
        /// </summary>
        /// <param name="RoadUriBuilder">示例 new UriBuilder("http://r2.tiles.ditu.live.com/tiles/r{quadkey}.png?g=49");</param>
        /// <param name="FullExtent">本地圖區域</param>
        /// <param name="MaxLeval">最大縮放級別</param>
        /// <param name="MinLeval">最小縮放級別</param>
        public TileLayerBingMapExpand(Uri RoadUriBuilder, Envelope FullExtent, int MaxLevel, int MinLevel)
        {
            //線路URL
            uriTemplate = RoadUriBuilder.ToString();
            this.FullExtent = FullExtent;
            /// <summary>
            ///  全地圖最大顯示區域
            /// </summary>
            _fullExtent = FullExtent;
            /// <summary>
            ///  本地圖最大放大倍數
            /// </summary>
            _MaxLevel = MaxLevel;
            /// <summary>
            ///  本地圖最小放大倍數
            /// </summary>
            _MinLevel = MinLevel;
            base.SpatialReference = new SpatialReference(WKID);
        }

        /// <summary>
        ///構造一個圖層
        /// </summary>
        /// <param name="RoadUriBuilder">示例 new UriBuilder("http://r2.tiles.ditu.live.com/tiles/r{quadkey}.png?g=49");</param>
        /// <param name="FullExtent">本地圖區域</param>
        /// <param name="MaxLeval">最大縮放級別</param>
        /// <param name="MinLeval">最小縮放級別</param>
        public TileLayerBingMapExpand(Uri RoadUriBuilder, int MaxLevel, int MinLevel)
        {
            //線路URL
            uriTemplate = RoadUriBuilder.ToString();
            /// <summary>
            ///  本地圖最大放大倍數
            /// </summary>
            _MaxLevel = MaxLevel;
            /// <summary>
            ///  本地圖最小放大倍數
            /// </summary>
            _MinLevel = MinLevel;
            base.SpatialReference = new SpatialReference(WKID);
        }

        #endregion

        /// <summary>
        /// 計劃算出 get URL
        /// </summary>
        /// <param name="level">放大等級</param>
        /// <param name="row">行</param>
        /// <param name="col">列</param>
        /// <returns></returns>
        public override string GetTileUrl(int level, int row, int col)
        {

            if (string.IsNullOrEmpty(this.uriTemplate))
            {
                return null;
            }
            StringBuilder builder = new StringBuilder();
            for (int i = level; i >= 0; i--)
            {
                int num2 = ((int)1) << i;
                builder.Append((int)(((col & num2) >> i) | (((row & num2) != 0) ? 2 : 0)));
            }



            #region 自己加的測試用的代碼 目前主要用來分析如何從圖片轉換出經維度
           // ///圖片的高寬
           // int PicWidthHeight = 256;

           // Point 左上頂點 = new Point();
           // Point 右下角點 = new Point();

           // var x = 0;
           // var y = 0;
           // var z = 0;
           // TileSystem.QuadKeyToTileXY(builder.ToString(), out x, out y, out z);

           // string Quadkey = TileSystem.TileXYToQuadKey(x, y, z);


           // var PxX = 0;
           // var PxY = 0;
           // var PxZ = 0;
           // TileSystem.TileXYToPixelXY(x, y, out PxX, out PxY);
           // var GpsX = 0.0;
           // var GpsY = 0.0;
           // var GpsZ = 0.0;
           // TileSystem.PixelXYToLatLong(PxX, PxY, z, out GpsX, out GpsY);

           // 左上頂點 = new Point() { X = GpsX, Y = GpsY };


           // #region 開始計算右下角點
           //TileSystem.PixelXYToLatLong(PxX + PicWidthHeight, PxY + PicWidthHeight, z, out GpsX, out GpsY);
           // 右下角點 = new Point() { X = GpsX, Y = GpsY };

            //#endregion
            #endregion




            return this.uriTemplate.Replace("{quadkey}", builder.ToString());
        }

        /// <summary>
        /// 得到圖層的方法
        /// </summary>
        public override void Initialize()
        {

            //1、Tiling Scheme Origin；
            //2、切图的范围，也就是FullExtent；
            //3、SpatialReference；
            //4、TileInfo，包括切图的大小，级数，以及每级的Resolution；
            //5、最后就是重写GetTileUrl方法。



            ///默認最大最小放大倍數
            int from = _MinLevel;
            int to = _MaxLevel;
            TileInfo info = new TileInfo();
            info.SpatialReference = new SpatialReference(WKID);
            info.Origin = new MapPoint(-20037508.3427892, 20037508.3427892);
            #region 用戶初始化處理
            //如果用戶沒有初始
            if (_fullExtent == null)
            {

                this.FullExtent = new Envelope(-20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892);

            }
            else
            {
                //指定地圖範圍
                info.Origin = new MapPoint(180 * 4, -180 * 4);
            }

            #endregion

            info.Width = 256;
            info.Height = 256;
            info.Lods = new Lod[(to - from) + 2];
            base.TileInfo = info;

            int num3 = 2 * from;
            int num4 = 2 * from;
            double num5 = (this.FullExtent.Width / ((double)num3)) / ((double)base.TileInfo.Width);

            //初始化數組 用於處理 載入的級別
            //處理最大的放大級別. 這裏采用最大放大級別
            Lod[] loadArray = new Lod[to];
            for (int i = 0; i < to; i++)
            {
                Lod lod = new Lod();
                lod.Resolution = num5;
                loadArray[i] = lod;
                num4 *= 2;
                num3 *= 2;
                num5 *= 0.5;
            }
            //初始化放大等級總數
            base.TileInfo.Lods = loadArray;


            #region 這裏是以前的方法這裏已經不再采用
            //for (int i = 0; i < base.TileInfo.Lods.Length; i++)
            //{
            //    Lod lod = new Lod();
            //    lod.Resolution = num5;
            //    base.TileInfo.Lods[i] = lod;
            //    num4 *= 2;
            //    num3 *= 2;
            //    num5 *= 0.5;
            //}

            #endregion

            base.InitializationFailure = null;
            base.Initialize();

        }




        #region 此版本不支持
        private string oldLayerType = "a";

        /// <summary>
        /// 信賴項屬性 此版本不支持
        /// </summary>
        public static readonly DependencyProperty LayerStyleProperty = DependencyProperty.Register("LayerStyle", typeof(LayerType), typeof(Layer), new PropertyMetadata(new PropertyChangedCallback(
            (s, e)
            =>
            {
                TileLayerBingMapExpand BingMaplayer = (TileLayerBingMapExpand)s;
                //當前圖的類型
                string currentLayerTypeString = System.Text.UTF8Encoding.UTF8.GetString(BitConverter.GetBytes((int)e.NewValue).Take(1).ToArray(), 0, 1);
                BingMaplayer.uriTemplate = BingMaplayer.uriTemplate.Replace("/tiles/" + BingMaplayer.oldLayerType, "/tiles/" + currentLayerTypeString);
                BingMaplayer.Refresh();
                BingMaplayer.oldLayerType = currentLayerTypeString;
            }
            )));
        /// <summary>
        /// 信賴項屬性 此版本不支持
        /// </summary>
        public LayerType LayerStyle
        {
            get
            {
                return (LayerType)base.GetValue(LayerStyleProperty);
            }
            set
            {
                base.SetValue(LayerStyleProperty, value);
            }
        }


        /// <summary>
        /// 圖類型
        /// </summary>
        public enum LayerType
        {
            /// <summary>
            /// 線路 r
            /// </summary>
            Road = 'r',
            /// <summary>
            /// 衛星圖 a 
            /// http://t1.tiles.virtualearth.net/tiles/a13212110221.png?g=49
            /// </summary>
            Aerial = 'a',
            /// <summary>
            /// 帶標注的衛星圖 h
            /// http://t1.tiles.virtualearth.net/tiles/h13212110221.png?g=49
            /// </summary>
            AerialWithLabels = 'h'
        }
        #endregion






    }
}
